﻿using System;
using System.IO;
using System.Text;

namespace UtilZ.Dotnet.Ex.Base
{
    /// <summary>
    /// 流扩展类
    /// </summary>
    public static partial class StreamEx
    {
        private static Encoding _stringDefaultEncoding = Encoding.UTF8;
        /// <summary>
        /// 获取或设置字符串默认编码
        /// </summary>
        public static Encoding StringDefaultEncoding
        {
            get { return _stringDefaultEncoding; }
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException(nameof(value));
                }

                _stringDefaultEncoding = value;
            }
        }


        /// <summary>
        /// 写指定字节长度的字符串,按char写入 
        /// </summary>
        /// <param name="writer">BinaryWriter</param>
        /// <param name="str">要写入的字符串</param>
        /// <param name="length">写入字节数</param>
        public static void WriteCharFixByteLengthString(this BinaryWriter writer, string str, int length)
        {
            if (str == null)
            {
                for (int i = 0; i < length; i++)
                {
                    writer.Write((byte)0);
                }
            }
            else
            {

                long endPos = writer.BaseStream.Position + length;
                for (int i = 0; i < str.Length; i++)
                {
                    writer.Write(str[i]);
                    if (writer.BaseStream.Position > endPos)
                    {
                        writer.BaseStream.Position = endPos;
                        return;
                    }
                    else if (writer.BaseStream.Position == endPos)
                    {
                        return;
                    }
                }

                while (writer.BaseStream.Position < endPos)
                {
                    writer.Write((byte)0);
                }
            }
        }

        /// <summary>
        /// 写指定字节长度的字符串
        /// </summary>
        /// <param name="writer">BinaryWriter</param>
        /// <param name="str">要写入的字符串</param>
        /// <param name="length">写入字节数</param>
        /// <param name="encoding">符串编码,当为null时按字符读写,不为null时按编解码读写</param>
        public static void WriteFixByteLengthString(this BinaryWriter writer, string str, int length, Encoding encoding)
        {
            if (str == null)
            {
                for (int i = 0; i < length; i++)
                {
                    writer.Write((byte)0);
                }
            }
            else
            {
                if (encoding == null)
                {
                    encoding = _stringDefaultEncoding;
                }

                byte[] buffer = encoding.GetBytes(str);
                if (buffer.Length >= length)
                {
                    writer.Write(buffer, 0, length);
                }
                else
                {
                    writer.Write(buffer, 0, buffer.Length);
                    for (int i = buffer.Length; i < length; i++)
                    {
                        writer.Write((byte)0);
                    }
                }
            }
        }






        /// <summary>
        /// 读取指定字节长度的字符串,按char读取
        /// </summary>
        /// <param name="reader">BinaryReader</param>
        /// <param name="length">读取字节数</param>
        /// <returns>读取到的字符串</returns>
        public static string ReadCharFixByteLengthString(this BinaryReader reader, int length)
        {
            return new string(reader.ReadChars(length)).Trim('\0');
        }

        /// <summary>
        /// 读取指定字节长度的字符串
        /// </summary>
        /// <param name="reader">BinaryReader</param>
        /// <param name="length">读取字节数</param>
        /// <param name="encoding">符串编码,当为null时按字符读写,不为null时按编解码读写</param>
        /// <returns>读取到的字符串</returns>
        public static string ReadFixByteLengthString(this BinaryReader reader, int length, Encoding encoding)
        {
            if (encoding == null)
            {
                encoding = _stringDefaultEncoding;
            }

            return encoding.GetString(reader.ReadBytes(length)).Trim('\0');
        }
    }

}
